package stone926.mods.more_enchantments.mixins;

import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.SmallFireballEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import stone926.mods.more_enchantments.enchantments.EnhancedSmallFireballEnchantment;
import stone926.mods.more_enchantments.interfaces.IPlayerEntityBlaze;
import stone926.mods.more_enchantments.interfaces.ISmallFireballEnhanced;

import static stone926.mods.more_enchantments.nbt.CustomNbtKeys.PLAYER_BLAZE.*;

@Mixin(PlayerEntity.class)
public abstract class PlayerEntityMixinBlaze extends LivingEntityMixin implements IPlayerEntityBlaze {

  private int shootCount = 0;
  private int shootCooldown = -1;
  private int boost = 0;
  private boolean shouldShoot = false;

  public PlayerEntityMixinBlaze(EntityType<?> type, World world) {
    super(type, world);
  }

  @Override
  public void shoot(int shootCount, int shootCooldown) {
    this.shootCooldown = Math.min(this.shootCooldown, shootCooldown);
    this.shootCount += shootCount;
    shouldShoot = true;
  }

  @Override
  public void boost(int lvl) {
    this.boost = lvl;
  }

  @Inject(method = "tick", at = @At("HEAD"))
  private void tickFireballShoot(CallbackInfo ci) {
    if (!shouldShoot) return;
    if (shootCooldown >= 0) {
      shootCooldown--;
    }
    if (shootCooldown == -1) {
      shootFireball();
      shootCount--;
      if (shootCount <= 0) {
        shootCount = 0;
        shouldShoot = false;
      } else {
        if (shootCount <= 13) shootCooldown = 6;
        else if (shootCount < 30) shootCooldown = 1;
        else shootCount = 0;
      }
    }
  }

  private void shootFireball() {
    PlayerEntity self = (PlayerEntity) (Object) this;
    float f1 = -MathHelper.sin(self.getYaw() * 0.017453292F) * MathHelper.cos(self.getPitch() * 0.017453292F);
    float f2 = -MathHelper.sin((self.getPitch() + self.getRoll()) * 0.017453292F);
    float f3 = MathHelper.cos(self.getYaw() * 0.017453292F) * MathHelper.cos(self.getPitch() * 0.017453292F);
    SmallFireballEntity smallFireball = new SmallFireballEntity(world, self, f1, f2, f3);
    smallFireball.setPosition(
      getX(),
      smallFireball.getY() +
        self.getEyeHeight(self.getPose()) -
        smallFireball.getEyeHeight(smallFireball.getPose()),
      getZ()
    );
    smallFireball.setVelocity(
      self,
      getPitch(), getYaw(), 0,
      1.2F + random.nextFloat() + 0.1F * boost,
      Math.max(0F, 5F - EnhancedSmallFireballEnchantment.getModifierXYZDecrement(boost))
    );
    ((ISmallFireballEnhanced) smallFireball).setBoost(boost);
    world.spawnEntity(smallFireball);
  }

  @Inject(method = "writeCustomDataToNbt", at = @At("HEAD"))
  protected void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo ci) {
    nbt.putInt(SHOOT_COUNT, shootCount);
    nbt.putInt(SHOOT_COOLDOWN, shootCooldown);
    nbt.putBoolean(SHOULD_SHOOT, shouldShoot);
    nbt.putInt(BOOST, boost);
  }

  @Inject(method = "readCustomDataFromNbt", at = @At("HEAD"))
  protected void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) {
    if (nbt.contains(SHOOT_COUNT)) shootCount = nbt.getInt(SHOOT_COUNT);
    if (nbt.contains(SHOOT_COOLDOWN)) shootCooldown = nbt.getInt(SHOOT_COOLDOWN);
    if (nbt.contains(SHOULD_SHOOT)) shouldShoot = nbt.getBoolean(SHOULD_SHOOT);
    if (nbt.contains(BOOST)) boost = nbt.getInt(BOOST);
  }

}
